package KNNCalculate;

import java.util.*;
import java.util.Map.Entry;

/**
 * Created by Administrator on 2016/12/3 0003.
 * 此算法通过调用计算出的矢量值来计算待分类文字与库中文字的距离，并求出最邻近的文字类
 */
public class KNN extends DVM{
    HashMap<String, Double> dist = new HashMap<String, Double>(); // 等分类文档互每个训练集文档的距离
    public Vector<Double> uv = new Vector<Double>();// 待分类文档的向量表示
    public static DVM dvm=new DVM();

/*
 * 待分类文档的向量获取getUv
 */
    public void getUv(String receiveList){
        AnswerList reList =new AnswerList();
        reList.extractMatrix(receiveList);
        DVM uv_dvm=new DVM();
        uv_dvm.buildDVM(0,receiveList,reList.wordfreq);
        uv=uv_dvm.dv.get(String.valueOf(0));
    }
    public KNN(){
        dvm.Build();
    }

    public void calDist(HashMap<String, Vector<Double>> fin_dv,String receiveList) {//fin_dv:训练集文档的归一向量表示
        getUv(receiveList);
        for (int i=0;i<fin_dv.size();i++) {
                Vector<Double> v_f = fin_dv.get(String.valueOf(i));
                int len = v_f.size();
                double d = cos(v_f, uv, len);
                if(d>0.0){
                    dist.put(String.valueOf(i), d);
                    System.out.println("到"+i+"的距离是"+d);}
        }
    }
    // 计算两个向量的夹角的余弦。如果此值的绝对值越大，说明夹角越小，越相似，距离越近。
    public double cos(Vector<Double> v1, Vector<Double> v2, int len) {
        double res = 0.0;
        double mul = 0.0;
        double p1 = 0.0, p2 = 0.0;
        for (int i = 0; i < len; i++) {
            double one = v1.get(i);
            double two = v2.get(i);
            mul += one * two;
            p1 += Math.pow(one, 2);
            p2 += Math.pow(two, 2);
        }
        res = Math.abs(mul) / Math.sqrt(p1 * p2);
        return res;
    }

    public void knn(int k){
        //对新向量到所有训练向量的距离按从大到小排序
        ArrayList<Entry<String,Double>> dist_list=featureSelect.build_IG.sort(dist);
        int c1=0,c2=0;
        for(int i=0;i<k;i++){
            Entry<String,Double> entry=dist_list.get(i);
            int fileNum=Integer.parseInt(entry.getKey());
            if(fileNum>=0 && fileNum<3)
                c1++;
            else if(fileNum>=3 && fileNum<6)
                c2++;
        }
        if(c1>c2)
            System.out.println("属于第1类！");
        else if(c2>1)
            System.out.println("属于第2类！");
        else
            System.out.println("属于两类的可能性一样大！");
    }


}
